package activity

import (
	"end/config"
	"end/entry"
	"end/httpEntry"
	"end/service/order"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/jinzhu/copier"
	"net/http"
	"strconv"
	"time"
)

type AuditRequest struct {
	Status     int `json:"status" binding:"required"`
	ActivityId int `json:"activityid" binding:"required"`
}

// AuditActivity 活动审核
func AuditActivity(r *gin.Engine) {
	r.POST("/activity/audit", httpEntry.LoginMiddleware(), httpEntry.AdminMiddleware(), func(c *gin.Context) {
		var auditRequest AuditRequest
		err := c.ShouldBind(&auditRequest)
		if err != nil {
			c.JSON(http.StatusOK, httpEntry.BaseResponse{
				Code:  10006,
				Error: httpEntry.ERROR10006,
			})
			return
		}
		allinfo := c.MustGet("allinfo").(config.AllInfo)
		if allinfo.Level&httpEntry.Admin == 0 {
			c.JSON(http.StatusOK, httpEntry.BaseResponse{
				Code:  10011,
				Error: httpEntry.ERROR10011,
			})
			return
		}
		var activity entry.Activity
		db := config.GetDb()
		result := db.Where("id = ?", auditRequest.ActivityId).First(&activity)
		if result.Error != nil {
			c.JSON(http.StatusOK, httpEntry.BaseResponse{
				Code:  10005,
				Error: httpEntry.ERROR10005,
			})
			return
		}
		// 更新
		if allinfo.Level&config.ADMIN1 != 0 {
			activity.StatusFirst = auditRequest.Status
			if activity.StatusFirst&httpEntry.STATUS2 != 0 {
				activity.Status = httpEntry.STATUS2
			} else {
				activity.Status = config.STATUS3
			}
		} else if allinfo.Level&config.ADMIN2 != 0 {
			activity.StatusTwo = auditRequest.Status
			if activity.StatusTwo&config.STATUS2 == 0 {
				activity.Status = config.STATUS3
			}
		} else {
			c.JSON(http.StatusOK, httpEntry.BaseResponse{
				Code:  10013,
				Error: httpEntry.ERROR10013,
			})
		}
		db.Updates(&activity)
		c.JSON(http.StatusOK, httpEntry.BaseResponse{
			Code:    200,
			Message: "操作成功",
		})
	})
}

type Activity struct {
	Title                 string    `json:"title" binding:"required"`
	Type                  string    `json:"type" binding:"required"`
	Integral              int       `json:"integral" gorm:"column:integral"`
	FirstImg              string    `json:"first_img" binding:"required"`
	RegistrationStarttime time.Time `json:"registration_starttime" binding:"required"`
	RegistrationDeadline  time.Time `json:"registration_deadline" binding:"required"`
	StartTime             time.Time `json:"starttime" binding:"required"`
	EndTime               time.Time `json:"endtime" binding:"required"`
	Num                   int       `json:"num" binding:"required"`
	Value                 string    `json:"value" binding:"required"`
	Address               string    `json:"address" binding:"required"`
}

// CreateActivity 创建活动
func CreateActivity(r *gin.Engine) {
	r.POST("/activity/create", httpEntry.LoginMiddleware(), httpEntry.AdminMiddleware(), func(context *gin.Context) {
		userInfo := context.MustGet("userinfo").(config.UserInfo)
		var activity Activity
		err := context.ShouldBind(&activity)
		if err != nil {
			fmt.Println(err.Error())
			context.JSON(http.StatusOK, httpEntry.BaseResponse{
				Code:  10006,
				Error: httpEntry.ERROR10006,
			})
			return
		}
		now := time.Now()

		// 检测创建时间
		if activity.RegistrationDeadline.Before(activity.RegistrationStarttime) ||
			activity.StartTime.Before(activity.RegistrationDeadline) ||
			activity.EndTime.Before(activity.StartTime) || activity.EndTime.Before(now) {
			context.JSON(http.StatusOK, httpEntry.BaseResponse{
				Code:  10029,
				Error: "时间参数错误",
			})
			return
		}
		var events entry.Activity
		_ = copier.Copy(&events, &activity)
		events.AdminID = userInfo.Id
		events.Status = httpEntry.STATUS1
		events.StatusFirst = httpEntry.STATUS1
		events.StatusTwo = httpEntry.STATUS1
		//minutes := events.EndTime.Sub(events.StartTime).Minutes()
		//events.Integral = int(minutes / 60 * 5)
		events.Look = 0
		events.AlreadyNum = 0
		fmt.Println(userInfo.Identity)
		switch userInfo.Identity {
		case "admin3":
			events.StatusFirst = httpEntry.STATUS1
			events.StatusTwo = httpEntry.STATUS1
		case "admin2":
			// 创建活动，等待二级管理员审核
			events.StatusFirst = httpEntry.STATUS1
			events.StatusTwo = httpEntry.STATUS2
		case "admin1":
			// 创建活动并发布
			events.StatusFirst = httpEntry.STATUS2
			events.StatusTwo = httpEntry.STATUS2
			events.Status = httpEntry.STATUS2
		}
		events.CreateTime = now
		if err := config.GetDb().Create(&events).Error; err != nil {
			context.JSON(http.StatusOK, httpEntry.BaseResponse{
				Code:  10005,
				Error: httpEntry.ERROR10005,
			})
			return
		}
		context.JSON(http.StatusOK, gin.H{
			"code":       200,
			"message":    "创建成功",
			"activityid": events.ID,
		})
	})
}

// DeleteActivity 仅允许自己删除活动
func DeleteActivity(r *gin.Engine) {
	r.GET("/activity/del/:id", httpEntry.LoginMiddleware(), httpEntry.AdminMiddleware(), func(c *gin.Context) {
		aid := c.Param("id")
		userinfo := c.MustGet("userinfo").(config.UserInfo)
		allinfo := c.MustGet("allinfo").(config.AllInfo)
		var activity entry.Activity
		db := config.GetDb()
		var err error
		if allinfo.Level&config.ADMIN1 != 0 {
			err = db.Where("id = ?", aid).First(&activity).Error
		} else {
			err = db.Where("id = ? and admin_id = ?", aid, userinfo.Id).First(&activity).Error
		}
		if err != nil {
			c.JSON(http.StatusOK, httpEntry.BaseResponse{
				Code:  10005,
				Error: httpEntry.ERROR10005,
			})
			return
		}
		// 判断活动是否在运行
		now := time.Now()
		// 如果当前时间在开始时间之后，就不可以删除了
		if activity.EndTime.After(now) {
			c.JSON(http.StatusOK, httpEntry.BaseResponse{
				Code:  10005,
				Error: "已经超过结束时间，不允许删除了",
			})
			return
		}
		// 删除活动
		db.Delete(activity)
		// 删除活动报名
		db.Delete(&entry.Eventregistration{}).Where("activityid = ?", activity.ID)
		c.JSON(http.StatusOK, httpEntry.BaseResponse{
			Code:    200,
			Message: "删除成功",
		})
	})
}

type Dto struct {
	entry.Activity
	Admin entry.Admin `json:"admin" gorm:"foreignkey:AdminID"`
}

func (Dto) TableName() string {
	return "activity"
}

// ShowActivityDetail 获活动详情
func ShowActivityDetail(r *gin.Engine) {
	r.GET("/activity/show/:id", httpEntry.LoginMiddleware(), func(c *gin.Context) {
		activityId := c.Param("id")
		aid, err := strconv.Atoi(activityId)
		if err != nil {
			c.JSON(http.StatusOK, httpEntry.BaseResponse{
				Code:  10014,
				Error: httpEntry.ERROR10014,
			})
			return
		}
		db := config.GetDb()
		// 查询
		var activity Dto
		result := db.Preload("Admin").Where("id = ?", aid).First(&activity)
		if result.Error != nil {
			c.JSON(http.StatusOK, httpEntry.BaseResponse{
				Code:  10005,
				Error: httpEntry.ERROR10005,
			})
			return
		}
		activity.Look++
		// 更新
		db.Table("activity").Where("id = ?", aid).Update("look", activity.Look)
		// 查询是否已经报名
		userinfo := c.MustGet("userinfo").(config.UserInfo)
		var event entry.Eventregistration
		db.Where("userid = ? and activityid = ?", userinfo.Id, activityId).First(&event)
		c.JSON(http.StatusOK, gin.H{
			"code":    200,
			"message": "查询成功",
			"data":    activity,
			"status":  event.Status,
			"eventid": event.ID,
		})
	})
}

type PageInfo struct {
	PageNum int `json:"pageNum" binding:"required"`
	Type    int `json:"type" binding:"required"`
}

type PageInfoAdmin struct {
	Page   int `json:"page" binding:"required"`
	Status int `json:"status" binding:"required"`
}

type PortInfo struct {
	ID                    int       `json:"id" gorm:"column:id"`
	Title                 string    `json:"title" gorm:"column:title"`
	Type                  string    `json:"type" gorm:"column:type"`
	FirstImg              string    `json:"first_img" gorm:"column:first_img"`
	RegistrationStarttime time.Time `json:"registration_starttime" gorm:"column:registration_starttime"`
	RegistrationDeadline  time.Time `json:"registration_deadline" gorm:"column:registration_deadline"`
	StartTime             time.Time `json:"starttime" gorm:"column:starttime"`
	EndTime               time.Time `json:"endtime" gorm:"column:endtime"`
	Num                   int       `json:"num" gorm:"column:num"`
	AlreadyNum            int       `json:"already_num" gorm:"column:already_num"`
	Integral              int       `json:"integral" gorm:"column:integral"`
	Look                  int       `json:"look" gorm:"column:look"`
	Address               string    `json:"address" gorm:"column:address"`
	CreateTime            time.Time `json:"createtime" gorm:"column:createtime"`
}

func (PortInfo) TableName() string {
	return "activity"
}

// ShowEvents 用户查看的活动
func ShowEvents(r *gin.Engine) {
	r.POST("/activity/show/user", httpEntry.LoginMiddleware(), func(c *gin.Context) {
		var pageInfo PageInfo
		if err := c.ShouldBind(&pageInfo); err != nil {
			c.JSON(http.StatusOK, httpEntry.BaseResponse{
				Code:  10006,
				Error: httpEntry.ERROR10006,
			})
			return
		}
		db := config.GetDb()
		var activities []PortInfo
		now := time.Now()
		// 全部
		if pageInfo.Type == 1 {
			db.Where("status & ?", config.STATUS2).
				Order("createtime desc").Offset(30 * (pageInfo.PageNum - 1)).Limit(30).Find(&activities)
			// 报名中
		} else if pageInfo.Type == 2 {
			db.Where("status & ? and registration_starttime <= ? and registration_deadline >= ?", config.STATUS2, now, now).
				Order("createtime desc").Offset(30 * (pageInfo.PageNum - 1)).Limit(30).Find(&activities)
			// 活动中
		} else if pageInfo.Type == 3 {
			//db.Where("status & ? and starttime <= ? and endtime >= ?", config.STATUS2, now, now).
			//	Order("createtime desc").Offset(30 * (pageInfo.PageNum - 1)).Limit(30).Find(&activities)
			// 未开始
			db.Where("status & ? and registration_starttime > ?", config.STATUS2, now).
				Order("createtime desc").Offset(30 * (pageInfo.PageNum - 1)).Limit(30).Find(&activities)
			// 已结束
		} else if pageInfo.Type == 4 {
			db.Where("status & ? and endtime < ?", config.STATUS2, now).
				Order("createtime desc").Offset(30 * (pageInfo.PageNum - 1)).Limit(30).Find(&activities)
		} else {
			c.JSON(http.StatusOK, httpEntry.BaseResponse{
				Code:  10006,
				Error: httpEntry.ERROR10006,
			})
			return
		}

		c.JSON(http.StatusOK, gin.H{
			"code":    200,
			"message": "请求成功",
			"data":    activities,
		})
	})
}

// GetEventsAudit 需要管理员审核的活动
func GetEventsAudit(r *gin.Engine) {
	r.POST("/activity/show/admin", httpEntry.LoginMiddleware(), func(c *gin.Context) {
		var pageInfo PageInfoAdmin
		if err := c.ShouldBind(&pageInfo); err != nil {
			c.JSON(http.StatusOK, httpEntry.BaseResponse{
				Code:  10006,
				Error: httpEntry.ERROR10006,
			})
			return
		}
		allinfo := c.MustGet("allinfo").(config.AllInfo)
		db := config.GetDb()
		var activities []entry.Activity
		// 如果是一级管理员
		if allinfo.Level&config.ADMIN1 != 0 {
			db.Where("status_two & ? and status_first & ?", httpEntry.STATUS2, pageInfo.Status).
				Order("createtime desc").Offset(30 * (pageInfo.Page - 1)).Limit(30).Find(&activities)
		} else if allinfo.Level&config.ADMIN2 != 0 {
			db.Where("status_two & ?", pageInfo.Status).
				Order("createtime desc").Offset(30 * (pageInfo.Page - 1)).Limit(30).Find(&activities)
		}
		c.JSON(http.StatusOK, gin.H{
			"code":    200,
			"message": "请求成功",
			"data":    activities,
		})
	})
}

// CreateAllActivity 我发布的活动
func CreateAllActivity(r *gin.Engine) {
	r.GET("/admin/all/activity/:page", httpEntry.LoginMiddleware(), httpEntry.AdminMiddleware(), func(context *gin.Context) {
		userinfo := context.MustGet("userinfo").(config.UserInfo)
		pageStr := context.Param("page")
		page, err := strconv.Atoi(pageStr)
		if err != nil {
			context.JSON(http.StatusOK, httpEntry.BaseResponse{
				Code:  10006,
				Error: httpEntry.ERROR10006,
			})
			return
		}
		var activitys []entry.Activity
		db := config.GetDb()
		db.Where("admin_id = ?", userinfo.Id).Offset((page - 1) * 30).
			Limit(30).Order("createtime desc").Find(&activitys)
		context.JSON(http.StatusOK, gin.H{
			"code":    200,
			"message": "获取成功",
			"data":    activitys,
		})
	})
}

type CreateRequest struct {
	ActivityId int `json:"activityId" binding:"required"`
	Status     int `json:"status" binding:"required"`
}

// CreateActivityScan 创建活动二维码
func CreateActivityScan(r *gin.Engine) {
	r.POST("/activity/scan", httpEntry.LoginMiddleware(), httpEntry.AdminMiddleware(), func(context *gin.Context) {
		userinfo := context.MustGet("userinfo").(config.UserInfo)
		var createRequest CreateRequest
		err := context.ShouldBind(&createRequest)
		if err != nil {
			context.JSON(http.StatusOK, httpEntry.BaseResponse{
				Code:  10006,
				Error: httpEntry.ERROR10006,
			})
			return
		}
		db := config.GetDb()
		var activity entry.Activity
		tx := db.Where("id = ? and admin_id = ?", createRequest.ActivityId, userinfo.Id).First(&activity)
		if tx.Error != nil {
			context.JSON(http.StatusOK, httpEntry.BaseResponse{
				Code:  10006,
				Error: httpEntry.ERROR10006,
			})
			return
		}
		value := ""
		if createRequest.Status&httpEntry.STATUS1 == 0 {
			value = strconv.Itoa(createRequest.ActivityId) + "|" + "0"
		} else {
			value = strconv.Itoa(createRequest.ActivityId) + "|" + "1"
		}
		timestamp := strconv.FormatInt(time.Now().Unix(), 10)
		value += "|" + timestamp
		encrypt, err := config.Encrypt(value)
		if err != nil {
			context.JSON(http.StatusOK, httpEntry.BaseResponse{
				Code:  10014,
				Error: httpEntry.ERROR10014,
			})
			return
		}
		code, err := order.GenerateBase64QRCode(encrypt)
		if err != nil {
			context.JSON(http.StatusOK, httpEntry.BaseResponse{
				Code:  10014,
				Error: httpEntry.ERROR10014,
			})
			return
		}
		context.JSON(200, gin.H{
			"code": 200, "qrcode": code,
		})
	})
}
